package com.wjw.cloud.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wjw.cloud.mapper.GoodsMapper;
import com.wjw.cloud.model.Goods;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class ElasticSearchUtil {

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    public boolean bulkInsert()
    {
        BulkRequest bulkRequest = new BulkRequest();

        bulkRequest.timeout("10s");

        List<Goods> goods = goodsMapper.selectListByPage(null, null, null);

        if (goods != null && goods.size() > 0)
        {
            for (int i = 0; i < goods.size(); i++) {
                bulkRequest.add(
                        new IndexRequest("great_goods")
                                .id("" + (i + 1))
                                .source(JSON.toJSONString(goods.get(i)), XContentType.JSON)
                );
            }
        }

        BulkResponse bulkResponse = null;

        try {
            bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (bulkResponse != null) {
            return !bulkResponse.hasFailures();
        } else {
            return false;
        }
    }

    public void deleteDocument()
    {
        log.info("=======开始删除文档数据=======");

        SearchRequest sRequest = new SearchRequest("great_goods");

        SearchSourceBuilder builder = new SearchSourceBuilder();
        MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
        builder.query(matchAllQueryBuilder)
                .timeout(new TimeValue(60, TimeUnit.SECONDS));

        sRequest.source(builder);

        long count = 0;

        try {
            SearchResponse search = client.search(sRequest, RequestOptions.DEFAULT);
            TotalHits totalHits = search.getHits().getTotalHits();
            count = totalHits.value;
        } catch (IOException e) {
            e.printStackTrace();
        }

        for (int i = 1; i <= count; i++) {
            DeleteRequest dRequest = new DeleteRequest("great_goods", String.valueOf(i));

            dRequest.timeout("1s");

            DeleteResponse delete = null;

            try {
                delete = client.delete(dRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                e.printStackTrace();
            }

            log.info(String.valueOf(delete.status()));
        }

        log.info("=======删除文档数据结束=======");
    }

    public HashMap<String, Object> searchDocument(String key, String value, int pageNum, int pageSize)
    {
        CountRequest great_goods = new CountRequest("great_goods");
        CountResponse countRes = null;
        try {
            countRes = client.count(great_goods, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        long count = countRes.getCount();
        int currentPage = (pageNum - 1) * pageSize;
        int pageTotal = (int) (Math.ceil((double) count / pageSize));

        SearchRequest request = new SearchRequest("great_goods");

        SearchSourceBuilder builder = new SearchSourceBuilder();

        // 判断 value 值是否为空，为空就查询全部
        if ("".equals(value)) {

            MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
            builder.query(matchAllQueryBuilder)
                    .from(currentPage)
                    .size(pageSize)
                    .timeout(new TimeValue(60, TimeUnit.SECONDS));

        } else {

            MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(key, value);
            builder.query(matchQueryBuilder)
                    .from(currentPage)
                    .size(pageSize)
                    .timeout(new TimeValue(60, TimeUnit.SECONDS));

        }

        request.source(builder);

        SearchResponse search = null;

        try {
            search = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        List<Goods> list = new ArrayList<>();

        if (search != null) {

            for (SearchHit hit : search.getHits().getHits()) {
                Map<String, Object> map = hit.getSourceAsMap();
                String jsonStr = JSONObject.toJSONString(map);
                Goods goods = JSONObject.parseObject(jsonStr, Goods.class);
                list.add(goods);
            }

        }

        HashMap<String, Object> map = new HashMap<>();
        map.put("pageNum", pageNum);
        map.put("pageSize", pageSize);
        map.put("totalPage", pageTotal);
        map.put("total", count);
        map.put("list", list);

        return map;
    }

}
